﻿using System;
using System.Text.RegularExpressions;
using System.Web.Configuration;
using System.Web.Hosting;
using System.Web.UI.WebControls;

namespace Salient.Web.Administration.AppConfig
{
    public partial class DefineErrorPage : ApplicationConfigurationPage
    {
        private static readonly Regex _fileFilter = new Regex("\\.aspx$",
                                                              RegexOptions.Singleline |
                                                              RegexOptions.IgnoreCase |
                                                              RegexOptions.CultureInvariant |
                                                              RegexOptions.Compiled);

        private static readonly Regex _fileFilter2 = new Regex("\\.htm[l]?$",
                                                               RegexOptions.Singleline |
                                                               RegexOptions.IgnoreCase |
                                                               RegexOptions.CultureInvariant |
                                                               RegexOptions.Compiled);

        private WebAdminWithConfirmation Master
        {
            get { return (WebAdminWithConfirmation) base.Master; }
        }

        public void ErrorPage_ServerValidate(object sender, ServerValidateEventArgs e)
        {
            if (DefaultErrorRadioButton.Checked)
            {
                e.IsValid = true;
            }
            else
            {
                e.IsValid = (PagesTreeView.SelectedNode != null);
            }
        }

        private string GetDirectory(string path)
        {
            if (path == null)
            {
                return null;
            }

            if (path.LastIndexOf('/') == -1)
            {
                return "/";
            }

            return path.Substring(path.LastIndexOf('/') + 1);
        }

        private void Page_Init()
        {
            if (!IsPostBack)
            {
                // Note: treenodes persist when added in Init, before LoadViewState
                var n = new TreeNode(GetDirectory(ApplicationPath), ApplicationPath);
                n.SelectAction = TreeNodeSelectAction.None;
                PagesTreeView.Nodes.Add(n);
                PopulateDirectoriesAndFiles(n);
            }
        }

        private void Page_Load()
        {
            if (!IsPostBack)
            {
                string appPath = ApplicationPath;
                if (appPath != null && !appPath.Equals(String.Empty))
                {
                    DefineErrorPageTitle.Text = String.Format((string) GetLocalResourceObject("TitleForSite"), appPath);
                }

                System.Configuration.Configuration config = OpenWebConfiguration(appPath);
                var customErrorsSection = (CustomErrorsSection) config.GetSection("system.web/customErrors");

                string errorPageUrl = customErrorsSection.DefaultRedirect;
                if (String.IsNullOrEmpty(errorPageUrl))
                {
                    DefaultErrorRadioButton.Checked = true;
                    ToggleSettingErrorPageElements(false);
                }
                else
                {
                    ErrorPageRadioButton.Checked = true;

                    if (errorPageUrl.StartsWith("~/"))
                    {
                        errorPageUrl = errorPageUrl.Substring(2);
                    }
                    else if (errorPageUrl.StartsWith(appPath + "/"))
                    {
                        errorPageUrl = errorPageUrl.Substring(appPath.Length + 1);
                    }
                    else if (errorPageUrl.StartsWith("/"))
                    {
                        // Unexpected case, set warning message and return
                        SetWarningText(errorPageUrl);
                        return;
                    }

                    if (!PopulateSelectedErrorPage(errorPageUrl, PagesTreeView.Nodes[0]))
                    {
                        SetWarningText(customErrorsSection.DefaultRedirect);
                    }
                }

                WarningTable2.Visible = IsErrorModeOff();
            }
        }

        private void PopulateDirectoriesAndFiles(TreeNode parent)
        {
            VirtualDirectory vdir = GetVirtualDirectory(parent.Value);
            foreach (VirtualDirectory childVdir in vdir.Directories)
            {
                var newNode = new TreeNode(childVdir.Name, parent.Value + "/" + childVdir.Name);
                newNode.SelectAction = TreeNodeSelectAction.None;
                newNode.ImageToolTip = (string) GetGlobalResourceObject("GlobalResources", "FolderIcon");
                parent.ChildNodes.Add(newNode);
                PopulateDirectoriesAndFiles(newNode);
            }

            foreach (VirtualFile childVfile in vdir.Files)
            {
                if (_fileFilter.IsMatch(childVfile.Name) || _fileFilter2.IsMatch(childVfile.Name))
                {
                    var newNode = new TreeNode(childVfile.Name, parent.Value + "/" + childVfile.Name,
                                               "../images/aspx_file.gif");
                    newNode.SelectAction = TreeNodeSelectAction.Select;
                    newNode.ImageToolTip = (string) GetGlobalResourceObject("GlobalResources", "ASPXFileIcon");
                    parent.ChildNodes.Add(newNode);
                }
            }
        }

        private bool PopulateSelectedErrorPage(string path, TreeNode node)
        {
            // Traverse the tree to locate the page node
            int slashPos = path.IndexOf('/');
            string targetNodeText;
            if (slashPos == -1)
            {
                targetNodeText = path;
            }
            else
            {
                targetNodeText = path.Substring(0, slashPos);
            }

            foreach (TreeNode childNode in node.ChildNodes)
            {
                if (childNode.Text == targetNodeText)
                {
                    if (slashPos == -1)
                    {
                        // End case: path is completely matched
                        childNode.Selected = true;

                        // We walk back the path to expand the tree to show the node is selected
                        TreeNode parent = childNode.Parent;
                        while (parent != null)
                        {
                            parent.Expanded = true;
                            parent = parent.Parent;
                        }

                        return true;
                    }
                    else
                    {
                        string nextPath = path.Substring(targetNodeText.Length + 1);
                        return PopulateSelectedErrorPage(nextPath, childNode);
                    }
                }
            }

            return false;
        }

        public void SaveButton_Click(object sender, EventArgs e)
        {
            if (!IsValid)
            {
                return;
            }

            System.Configuration.Configuration config = OpenWebConfiguration(ApplicationPath);
            var customErrorsSection = (CustomErrorsSection) config.GetSection("system.web/customErrors");

            if (DefaultErrorRadioButton.Checked)
            {
                customErrorsSection.DefaultRedirect = string.Empty;
            }
            else
            {
                // Replace the app name with ~
                customErrorsSection.DefaultRedirect = "~" +
                                                      PagesTreeView.SelectedNode.Value.Substring(ApplicationPath.Length);
            }

            // Clear the warning that might have been set
            WarningTable.Visible = false;

            SaveConfig(config);

            // Go to confirmation UI
            Master.SetDisplayUI(true);
        }

        private bool IsErrorModeOff()
        {
            System.Configuration.Configuration config = OpenWebConfiguration(ApplicationPath);
            var customErrorsSection = (CustomErrorsSection) config.GetSection("system.web/customErrors");
            return (customErrorsSection.Mode == CustomErrorsMode.Off);
        }

        public void SetWarningText(string errorPageUrl)
        {
            WarningTable.Visible = true;
            WarningErrorPageUrlLabel.Text = errorPageUrl;
        }

        public void ToggleSettingErrorPageElements(bool enabled)
        {
            PagesPanel.Enabled = enabled;
            PagesTreeView.Enabled = enabled;
        }

        public void WebControl_ValueChanged(object sender, EventArgs e)
        {
            if (DefaultErrorRadioButton.Checked)
            {
                // De-select the previous setting and collapse all nodes
                TreeNode selectedNode = PagesTreeView.SelectedNode;
                if (selectedNode != null)
                {
                    selectedNode.Selected = false;
                }

                PagesTreeView.CollapseAll();
                WarningTable.Visible = false;
                ToggleSettingErrorPageElements(false);
            }
            else
            {
                ToggleSettingErrorPageElements(true);
            }

            if (IsErrorModeOff())
            {
                WarningTable2.Visible = true;
            }
            else
            {
                WarningTable2.Visible = false;
            }
        }

        // Confirmation's related handlers
        public void ConfirmOK_Click(object sender, EventArgs e)
        {
            ReturnToPreviousPage(sender, e);
        }
    }
}